﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using psafth.AMB;

namespace psafth.P3Tester
{
    class Program
    {
        private static int DEFAULT_INIT_KEY = 0xFFFF;
        private static int POLYNOMIAL = 0x1021; // 0001 0000 0010 0001  (0, 5, 12)

        static void Main(string[] args)
        {
            CRCTest("8e02330043df000001000104490c01000304c6e548000408e8f067b2e17b04000502a7000602f500080200008104e80904008f");

            //string[] inputData = new string[]{
            //    "8E0136003833000001000104110000000304377747000502450006026C00020101080200000408400D72A9000000008104540202008F",
            //    "8E01180013EC00000200010213000B01008104540202008F"
            //};

            //byte[] input = new byte[] { 0x8E, 0x01, 0x36, 0x00, 0x38, 0x33, 0x00, 0x00, 0x01, 0x00, 0x01, 0x04, 0x11, 0x00, 0x00, 0x00, 0x03, 0x04, 0x37, 0x77, 0x47, 0x00, 0x05, 0x02, 0x45, 0x00, 0x06, 0x02, 0x6C, 0x00, 0x02, 0x01, 0x01, 0x08, 0x02, 0x00, 0x00, 0x04, 0x08, 0x40, 0x0D, 0x72, 0xA9, 0x00, 0x00, 0x00, 0x00, 0x81, 0x04, 0x54, 0x02, 0x02, 0x00, 0x8F };

            //byte[] input = new byte[] { 0x8E, 0x01, 0x18, 0x00, 0x13, 0xEC, 0x00, 0x00, 0x02, 0x00, 0x01, 0x02, 0x13, 0x00, 0x0B, 0x01, 0x00, 0x81, 0x04, 0x54, 0x02, 0x02, 0x00, 0x8F };

            byte[] input = new byte[] { 0x8e, 0x02, 0x33, 0x00, 0xfc, 0xd4, 0x00, 0x00, 0x01, 0x00, 0x01, 0x04, 0x90, 0x09, 0x00, 0x00, 0x03, 0x04, 0xd7, 0xe6, 0x48, 0x00, 0x04, 0x08, 0x28, 0x56, 0xc7, 0xdf, 0xf2, 0xce, 0x04, 0x00, 0x05, 0x02, 0x5b, 0x00, 0x06, 0x02, 0x11, 0x00, 0x08, 0x02, 0x00, 0x00, 0x81, 0x04, 0xbe, 0x13, 0x04, 0x00, 0x8f };
            byte[] bytes = new byte[] { 0x8e, 0x02, 0x33, 0x00, 0xfc, 0xd4, 0x00, 0x00, 0x01, 0x00, 0x01, 0x04, 0x90, 0x09, 0x00, 0x00, 0x03, 0x04, 0xd7, 0xe6, 0x48, 0x00, 0x04, 0x08, 0x28, 0x56, 0xc7, 0xdf, 0xf2, 0xce, 0x04, 0x00, 0x05, 0x02, 0x5b, 0x00, 0x06, 0x02, 0x11, 0x00, 0x08, 0x02, 0x00, 0x00, 0x81, 0x04, 0xbe, 0x13, 0x04, 0x00, 0x8f };


            byte TOR = 0x24;
            byte[] FORs = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x08, 0x0A, 0x0C };

            //List<byte> data = new List<byte>();

            //data.Add(AMBMessage.SOR);
            //data.Add(0x02);
            //data.Add(0x00);
            //data.Add(0x00);
            //data.Add(0x00);
            //data.Add(0x00);
            //data.Add(0x00);
            //data.Add(0x00);
            //data.Add(TOR);
            //data.Add(0x00);

            //for (int i = 0; i < FORs.Length; i++)
            //{
            //    data.Add((byte)FORs[i]);
            //    data.Add((byte)0x0);
            //}

            //data.Add(AMBMessage.EOR);

            //return calculateCrcAndEsc(data);

            string a = "123456789";



            byte[] d = System.Text.Encoding.ASCII.GetBytes(a);

            int check = calculateCRC16CCIT(d);
        }

        public byte[] calculateCrcAndEsc(byte[] data)
        {
            data = updateCRC(data);
            //return P3Tools.processESC(data);

            return data;
        }


        private byte[] updateCRC(byte[] data)
        {
            int crc = calculateCRC16CCIT(data);
            //Bytes x = new Bytes();
            //x.addInt2((short)crc);
            //data.set(5, x.get(0));
            //data.set(4, x.get(1));
            return data;
        }

        public static int calculateCRC16CCIT(byte[] bytes)
        {
            return calculateCRC16CCIT(bytes, DEFAULT_INIT_KEY);
        }

        public static int calculateCRC16CCIT(byte[] bytes, int initKey)
        {
            return calc(bytes, initKey) & 0xFFFF;
        }

        private static int calc(byte[] bytes, int initKey)
        {
            int crc = initKey;
            foreach (byte b in bytes)
            {
                for (int i = 0; i < 8; i++)
                {
                    bool bit = ((b >> (7 - i) & 1) == 1);
                    bool c15 = ((crc >> 15 & 1) == 1);
                    crc <<= 1;
                    if (c15 ^ bit)
                    {
                        crc ^= POLYNOMIAL;
                    }
                }
            }
            return crc;
        }

        public static void ProcessInput(byte[] input)
        {
            TransferObject t = new TransferObject(input);

            if (t.MessageType == AMBMessageType.PASSING)
            {
                AMB.Passing p = new AMB.Passing(t.Data);
            }

            if (t.MessageType == AMBMessageType.STATUS)
            {
                AMB.Status s = new AMB.Status(t.Data);
            }
        }


        public static void CRCTest(string data)
        {

            // init
            List<byte> bytes = new List<byte>();
            int c = 0;
            for (int i = 0; i < data.Length / 2; i++)
            {
                String n = data.Substring(c, 2);
                int x = Byte.Parse(n, System.Globalization.NumberStyles.HexNumber);
                bytes.Add(BitConverter.GetBytes(x)[0]);
                c += 2;
            }

            if (bytes.Count != data.Length / 2)
            {
                Console.WriteLine("Conversion to bytes issue.Exit.");
            }

            // test
            int CRC = Convert.ToInt16(bytes[4]);
            CRC += Convert.ToInt16(bytes[5]) * 256;


            byte[] bytesFromList = bytes.ToArray();

            if (BitConverter.IsLittleEndian)
                Array.Reverse(bytesFromList);

            //int calcCRC = calculateCRC(bytes);
            uint calcCRC = AMBCalculator.CalculateCRC16(bytesFromList);

            bool crcIsOK;
            if (calcCRC == CRC) crcIsOK = true;
            else
                crcIsOK = false;

            if (crcIsOK) Console.WriteLine("CRC test ok");
            else Console.WriteLine("CRC test ERROR. Calculated:" + calcCRC + " expected:" + CRC);
        }
    }
}
